#ifndef __packet_x2000_ieu89e8u89u8__
#define __packet_x2000_ieu89e8u89u8__

#include <memory.h>
#include <chrono>

#include <hude/base/hex.hpp>
#include <hude/base/log.hpp>

namespace pgl
{
    namespace x2000
    {
        using uint_t = unsigned int;

        /*********************************************************************
         *   功能描述:
         *       实现CRC16计算
         *       为指定的数据计算CRC_16的校验值.
         *       计算公式：
         *       	 CRC_16= x^16 + x^15 + x^2 + 1
         *
         *   调用:
         *       char data[] = { ... };
         *       auto result = crc16_t::crc16( data );
         */
        template< typename _byte >
        struct crc16_t
        {
            typedef _byte byte_t;
            typedef const _byte* itr_t;

            template< typename _bytes >
            static inline uint16_t crc16( const _bytes& bs ) { return crc16_table( begin( bs ), end( bs ) ); }
            static inline uint16_t crc16( itr_t b, itr_t e ) { return crc16_table( b, e ); }

            static uint16_t crc16_table( itr_t, itr_t );
            static uint16_t crc16_calc ( itr_t, itr_t );
        };

        /******函数名:CRC16_CCITT() *********************
         *
         *   功能描述:
         *       这个函数为系统的CRC16的计算函数，将给定的CRC值和要
         *       计算的数据做CRC计算并将计算结果赋予前面给定的CRC值。
         *       计算公式：
         *       	 CRC_16= x^16 + x^12 + x^5 + 1
         *          包文： 5a0001021000080000000101020006ed08
         *          示例： 0001021000080000000101020006 结果为：ED08
         *   调用参数:
         *       pchMsg       要计算的数据直针
         *    	 wDataLen     数据长度
         *   返回值:
         *       wCRC 函数新计算的CRC值
         *
         *   函数代码:
         */
        template< typename _byte >
        uint16_t crc16_t< _byte >::crc16_calc( itr_t begin, itr_t end )
        {
            static const uint16_t crc16_xmodel_iv = 0x1021;

            unsigned char i;
            unsigned short ret = 0;
            for( auto p = begin; p != end; ++p )
            {
                ret ^= (((unsigned short)*p) << 8);

                for (i = 0; i < 8; i++)
                {
                    if (ret & 0x8000)
                        ret = (ret << 1) ^ crc16_xmodel_iv;
                    else
                        ret <<= 1;
                }
            }

            return ret;
        }

        //--------------------------------------------------------------------------------
        template< typename _byte >
        uint16_t crc16_t< _byte >::crc16_table( itr_t begin, itr_t end )
        {
            static const uint16_t table[256] = {
                0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
                0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
                0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
                0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
                0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
                0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
                0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
                0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
                0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
                0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
                0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
                0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
                0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
                0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
                0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
                0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
            };

            auto crc = []( byte_t target, uint16_t last )
            {
                return ( last << 8 ) ^ table [ ( last >> 8 ) ^ target ];
            };

            uint16_t result = 0;

            for( auto itr = begin; itr != end; ++itr )
            {
                result = crc( *itr, result );
            }

            return result;
        }

        template< typename _target >
        using _value_t = hude::utils::byte_order_t::value_t< _target, hude::utils::byte_order_t::emNET >;

        /*********************************************************************
         * @brief 协议头二进制结构
         */
        #pragma pack(1)
        struct _packet_head_t
        {
            // {{{ @ proto ctrl word
            uint8_t   proto;
            uint8_t   version;

            union
            {
                struct
                {
                    uint8_t  type   : 4;
                    uint8_t  event  : 1;
                    uint8_t  rs485  : 1;
                    uint8_t  unused : 2;
                };

                uint8_t byte;
            } option;

            uint8_t   message;
            // }}}

            union
            {
                uint8_t   b[2];
                uint16_t  v;
            } lenght;
        };
        #pragma pack()

        /*********************************************************************
         * @brief 协议头封装
         *  注意： 协议字段在协议头中不是字长对齐的, 所以其操作尽可能复制到临时变量中进行
         */
        struct packet_t
        {
            enum : size_t
            {
                emSIZ_HEAD     = sizeof(_packet_head_t),
                emSIZ_CRC      = sizeof(uint16_t),
                emMAX_BODY     = 1024U,
                emMIN_PKG      = 1 + emSIZ_HEAD + emSIZ_CRC,
                emMAX_PKG      = emMIN_PKG + emMAX_BODY,
            };

            enum : uint8_t
            {
                emIDENT        = 0x5A,
                emPROTO        = 0x00,
                emVERSION      = 0x01
            };

            enum : uint8_t
            {
                emTYPE_EXP  = 0,  // 读写器错误或告警消息。
                emTYPE_DEV  = 1,  // 读写器配置与管理消息。
                emTYPE_RFID = 2,  // RFID 配置与操作消息。
                emTYPE_LOG  = 3,  // 读写器日志消息。
                emTYPE_UPG  = 4,  // 读写器应用处理器软件与基带软件升级消息。
                emTYPE_TEST = 5,  // 测试指令。

                emTYPE_MAX
            };

            _packet_head_t head;

            static void set_default_head( _packet_head_t& h )
            {
                memset( &h, 0, sizeof( _packet_head_t ) );

                h.version = 1;
                h.option.type = 2;
            }

            packet_t()
            {
            }

            packet_t( uint32_t option, uint16_t body )
            {
                set_default_head( head );

                _value_t< uint32_t >::set( &head, option );

                lenght( body );
            }

            void copy_to( packet_t* pkt ) const { memcpy( pkt, this, size() - 1 ); }

            inline void lenght( uint16_t v ) { _value_t< uint16_t >::set( head.lenght.b, v ); }
            inline uint16_t lenght() const { return _value_t< uint16_t >::get( head.lenght.b ); }

            inline void event( bool v ) { head.option.type = v? 1U : 0U; }
            inline bool event() const { return (head.option.type)? true : false; }

            inline void type( uint8_t v ) { head.option.type = v; }
            inline uint8_t type() const { return head.option.type; }

            inline void mid( uint8_t v ) { head.message = v; }
            inline uint8_t mid() const { return head.message; }

            inline void option( uint8_t v ) { head.option.byte = v; }
            inline uint8_t option() const { return head.option.byte; }

            inline uint16_t crc( uint16_t siz ) const
            {
                auto b = (const uint8_t*)(const void*)this;
                auto e = b + siz + emSIZ_HEAD;
                return crc16_t< uint8_t >::crc16( b, e );
            }

            inline uint16_t get_crc( uint16_t siz ) const
            {
                auto b = (const uint8_t*)(const void*)this;
                auto e = b + emSIZ_HEAD + siz;

                return _value_t< uint16_t >::get( e );
            }

            inline void set_crc( uint16_t siz, uint16_t crc )
            {
                auto b = (uint8_t*)(void*)this;
                auto e = b + emSIZ_HEAD + siz;

                _value_t< uint16_t >::set( e, crc );
            }

            inline void set_crc( uint16_t siz )
            {
                set_crc( siz, crc( siz ) );
            }

            inline uint16_t size() const
            {
                return emMIN_PKG + lenght();
            }

            inline bool token( bool evt, uint8_t type, uint8_t mid ) const
            {
                bool ret = evt == head.option.event? true : false &&
                    type == head.option.type && mid == head.message;

                return ret;
            }

            inline bool check( uint16_t siz ) const
            {
                uint16_t crc_current = get_crc( siz );
                uint16_t crc_cala    = crc( siz );

                bool err = ( siz > emMAX_BODY || head.proto != emPROTO ||
                    head.version != emVERSION || crc_current != crc_cala );

                return !err;
            }

            template< typename _itr >
            static _itr find( _itr& b, _itr& e )
            {
                for( auto p = b; p != e; ++p )
                {
                    if( *p == emIDENT )
                    {
                        const size_t len = e - p;

                        if( len < emMIN_PKG )
                        {
                            return e;
                        }

                        auto h = p + 1;

                        auto packet = (packet_t*)&(*h);

                        auto bodys = packet->lenght();

                        if( bodys > emMAX_BODY ) continue;

                        if( len < emMIN_PKG + bodys )
                        {
                            return e;
                        }

                        if( packet->check( bodys ) )
                        {
                            b = p + bodys + emMIN_PKG;

                            return p;
                        } else {
                            const uint8_t* addr = &(*p);

                            llog_war( "<plug-x2000>", "crc16 error( %#x ), frame: %s", packet->get_crc( bodys ),
                                hude::utils::to_hex( addr, emMIN_PKG + bodys ).c_str() );
                        }
                    }
                }

                return ( b = e );
            }

            inline void to_buffer( hude::buffer_t& buffer ) const
            {
                auto siz = this->size();

                buffer.resize( siz );
                buffer[0] = emIDENT;

                memcpy( &(buffer[1]), this, siz - 1 );
            }

            inline hude::buffer_t to_buffer() const
            {
                hude::buffer_t buffer;
                to_buffer( buffer );
                return buffer;
            }

            static std::time_t now()
            {
                namespace chr = std::chrono;

                auto n = chr::time_point_cast< chr::milliseconds >( chr::system_clock::now() );

                return n.time_since_epoch().count();
            }
        };

        /*********************************************************************
         * request MID, 后面只定义了用到的命令
         */
        enum mid_t : uint8_t
        {
            emGET_INFO       = 0x00,  // 查询读写器 RFID 能力 任何状态
            emSET_POWER      = 0x01,  // 配置读写器功率 任何状态
            emGET_POWER      = 0x02,  // 查询读写器功率 空闲状态
            emSET_RF_BAND    = 0x03,  // 配置读写器 RF 频段 任何状态
            emGET_RF_BAND    = 0x04,  // 查询读写器 RF 频段 空闲状态
            emSET_RF_FREQ    = 0x05,  // 配置读写器工作频率 任何状态
            emGET_RF_FREQ    = 0x06,  // 查询读写器工作频率 任何状态
            emSET_ANTENNAS   = 0x07,  // 配置读写器天线 空闲状态
            emGET_ANTENNAS   = 0x08,  // 查询读写器天线 任何状态
            emSET_TAG        = 0x09,  // 配置标签上传参数 空闲状态
            emGET_TAG        = 0x0A,  // 查询标签上传参数 任何状态
            emSET_EPC        = 0x0B,  // 配置 EPC 基带参数 空闲状态
            emGET_EPC        = 0x0C,  // 查询 EPC 基带参数 任何状态
            emSET_IDLE       = 0x0D,  // 配置读写器自动空闲模式 空闲状态
            emGET_IDLE       = 0x0E,  // 查询读写器自动空闲模式 任何状态
            emSET_HOLD       = 0xE0,  // 配置天线和频点的驻留时长 空闲状态
            emGET_HOLD       = 0xE1,  // 查询天线和频点的驻留时长 空闲状态
            emREAD           = 0x10,  // 读 EPC 标签 空闲状态
            emWRITE          = 0x11,  // 写 EPC 标签 空闲状态
            emLOCK           = 0x12,  // 锁 EPC 标签 空闲状态
            emKILL           = 0x13,  // 灭活 EPC 标签
            emSTOP           = 0xff,  // 停止读标签
            emSTATE          = 0xaf,  // 侦测状态

            emREAD_TAG       = 0x00,  // 读 EPC 标签事件
            emREAD_END       = 0x01,  // 读 EPC 标签结束
            emREAD_ANT       = 0x02,  // 读 EPC 标签天线

            emERROR          = 0x00   // 错误
        };

        /*********************************************************************
         * @brief 指令请求的静态token定义
         */
        template< uint8_t _event, uint8_t _type, mid_t _mid >
        struct _token_t
        {
            enum value_t : uint32_t
            {
                emPROTO     = 0x00U,
                emVERSION   = 0x01U,

                emEVENT     = static_cast< uint32_t >( _event ),
                emTYPE      = static_cast< uint32_t >( _type  ),
                emMID       = static_cast< uint32_t >( _mid   ),

                emOPTION    = ( ( emEVENT << 4U ) | emTYPE ),
                emVALUE     = (emPROTO << 24U) | (emVERSION << 16) | (emOPTION << 8) | emMID
            };
        };

        /*********************************************************************
         * @brief 非mid特化版的读头请求封包
         */
        template< typename _option > struct packet_req_t : public packet_t
        {
            using token_t = _option;

            packet_req_t() : packet_t( token_t::emVALUE, 0U ) { set_crc( 0U ); }

            uint16_t crc16;
        };

        /*********************************************************************
         * @brief 非mid特化版的读头回应封包
         */
        template< typename _option > struct packet_res_t : public packet_t
        {
            using token_t = _option;

            enum : size_t { emBODY = 1U, emSIZE = emBODY + packet_t::emMIN_PKG };

            uint8_t body[emBODY + emSIZ_CRC];

            packet_res_t( uint8_t ret = 0 ) : packet_t( token_t::emVALUE, emBODY ) { body[0] = ret; set_crc( emBODY ); }

            uint8_t result() const { return body[0]; }
            void result( uint8_t v ) { body[0] = v; }
        };

        /*********************************************************************
         * @brief 非mid特化版的读头事件封包
         */
        template< typename _option > struct packet_evt_t : public packet_t
        {
            using token_t = _option;

            enum : size_t { emBODY = 1U, emSIZE = emBODY + packet_t::emMIN_PKG };

            uint8_t body[emBODY + emSIZ_CRC];

            packet_evt_t() : packet_t( token_t::emVALUE, emBODY ) { body[0] = 0; set_crc( emBODY ); }

            uint8_t result() const { return body[0]; }
            void result( uint8_t v ) { body[0] = v; }
        };

        /*********************************************************************
         * @brief 读头错误封包
         */
        struct packet_err_t : public packet_t
        {
            using token_t = _token_t< 0x01, 0x00, mid_t::emERROR >;

            enum : size_t { emBODY = 6U, emSIZE = emBODY + packet_t::emMIN_PKG, emMID = 3U };

            enum : uint8_t { emSTATE_IDLE, emSTATE_INVENTORY, emSTATE_ERROR };

            uint8_t body[emBODY + emSIZ_CRC];

            packet_err_t()
            {
            }

            packet_err_t( uint8_t err, uint8_t sta, const packet_t& pkg ) :
                packet_err_t( err, sta, pkg.mid(), pkg.head.option.byte, pkg.lenght() )
            {
            }

            packet_err_t( uint8_t err, uint8_t sta, uint8_t mid, uint8_t opt, uint16_t siz ) :
                packet_t( token_t::emVALUE, emBODY )
            {
                body[0] = err;
                body[1] = sta;
                body[2] = opt;
                body[3] = mid;

                _value_t< uint16_t >::set( body + 4, siz );

                set_crc( emBODY );
            }

            uint8_t  error() const { return body[0]; }
            uint8_t  state() const { return body[1]; }
            mid_t    req() const { return (mid_t)(body[emMID]); }
            uint16_t target_ctrl() const { return _value_t< uint16_t >::get( body + 2U ); }
            uint16_t target_size() const { return _value_t< uint16_t >::get( body + 4U ); }
        };

        /*********************************************************************
         * 简化封包定义
         */
        template< mid_t _mid > struct token_req_t { typedef _token_t< 0x00, 0x02, _mid > type_t; };
        template< mid_t _mid > struct token_res_t { typedef _token_t< 0x00, 0x02, _mid > type_t; };
        template< mid_t _mid > struct token_evt_t { typedef _token_t< 0x01, 0x02, _mid > type_t; };

        /*********************************************************************
         * 简化封包定义
         */
        template< mid_t _mid > struct pkt_req_t { typedef packet_req_t< typename token_req_t< _mid >::type_t > type_t; };
        template< mid_t _mid > struct pkt_res_t { typedef packet_res_t< typename token_res_t< _mid >::type_t > type_t; };
        template< mid_t _mid > struct pkt_evt_t { typedef packet_evt_t< typename token_evt_t< _mid >::type_t > type_t; };

        /*********************************************************************
         * @brief 封包内的可选数据项结构
         */
        template< typename _value >
        struct argument_t
        {
            uint8_t pid;
            _value  value;
        };

        /*********************************************************************
         * @brief 标签数据
         */
        struct tag_t
        {
            hude::buffer_t epc;
            hude::buffer_t tid;
            uint16_t pc;
            uint8_t ant;
            uint8_t rssi;
            uint32_t freq;
            uint64_t utc;
        };

        /*********************************************************************
         * @brief 读头info查询回应封包
         */
        template<> struct packet_res_t< _token_t< 0x00, 0x02, mid_t::emGET_INFO > > : public packet_t
        {
            using token_t = _token_t< 0x00, 0x02, mid_t::emGET_INFO >;

            enum : size_t { emBODY = 4U, emSIZE = emBODY + emMIN_PKG };

            uint8_t power_min_;
            uint8_t power_max_;
            uint8_t antenna_max_;
            uint8_t more_[1];
            uint16_t crc;

            packet_res_t() : packet_t( token_t::emVALUE, emBODY ) {}

            uint8_t power_min() const { return power_min_; }
            uint8_t power_max() const { return power_max_; }
            uint8_t antenna_max() const { return antenna_max_; }

            uint16_t freq_count() const { return _value_t< uint16_t >::get( more_ + 0 ); }
            uint16_t proto_count() const { return _value_t< uint16_t >::get( more_ + 2 + freq_count() ); }

            uint8_t freqs ( uint16_t idx ) const { return more_[idx + 2]; }
            uint8_t protos( uint16_t idx ) const { return more_[idx + ( 2 + 2 ) + freq_count()]; }
        };

        /*********************************************************************
         * @brief 读头power设置请求封包
         */
        template<> struct packet_req_t< _token_t< 0x00, 0x02, mid_t::emSET_POWER > > : public packet_t
        {
            using token_t = _token_t< 0x00, 0x02, mid_t::emSET_POWER >;

            enum : uint_t { emANT_COUNT = 4U, emBODY = emANT_COUNT * 2 + 2 };

            packet_req_t( bool save = false ) : packet_req_t( nullptr, 0U, save ) {}

            packet_req_t( const argument_t< uint8_t >* dbs, size_t siz, bool save = false ) :
                packet_t( token_t::emVALUE, siz * 2 + 2 )
            {
                auto len = siz * 2;

                memcpy( body, dbs, len );

                body[len + 0] = 0xff;
                body[len + 1] = save? 1U : 0U;

                set_crc( siz * 2 + 2 );
            }

            uint8_t body[emBODY + emSIZ_CRC];
        };

        /*********************************************************************
         * @brief 读头power查询回应封包
         */
        template<> struct packet_res_t< _token_t< 0x00, 0x02, mid_t::emGET_POWER > > : public packet_t
        {
            using token_t = _token_t< 0x00, 0x02, mid_t::emGET_POWER >;

            enum : uint_t { emANT_COUNT = 4U, emBODY = emANT_COUNT * 2, emSIZE = emBODY + emMIN_PKG };

            uint8_t body[emBODY + emSIZ_CRC];

            packet_res_t() : packet_t( token_t::emVALUE, emBODY ) {}

            uint8_t power( uint8_t index ) const { return body[( index * 2 ) + 1]; }
            void power( uint8_t index, uint8_t v ) { body[( index * 2 ) + 1] = v; }
        };

        /*********************************************************************
         * @brief 读头rf-band频段设置请求封包
         */
        template<> struct packet_req_t< _token_t< 0x00, 0x02, mid_t::emSET_RF_BAND > > : public packet_t
        {
            using token_t = _token_t< 0x00, 0x02, mid_t::emSET_RF_BAND >;

            enum : uint_t { emBODY = 1U, emSIZE = emBODY + emMIN_PKG };

            packet_req_t( uint8_t band = 3U ) :
                packet_t( token_t::emVALUE, emBODY )
            {
                body[0] = band;

                set_crc( emBODY );
            }

            uint8_t body[emBODY + emSIZ_CRC];
        };

        // /*********************************************************************
        //  * @brief 读头rf-band频段查询回应封包
        //  */
        // PACKET_USE_DEFAULT_TEMPLTE( _token_t< 0x00, 0x02, mid_t::emGET_RF_BAND > );

        /*********************************************************************
         * @brief 读头rf-freq频点设置请求封包
         */
        template<> struct packet_req_t< _token_t< 0x00, 0x02, mid_t::emSET_RF_FREQ > > : public packet_t
        {
            using token_t = _token_t< 0x00, 0x02, mid_t::emSET_RF_FREQ >;

            packet_req_t( bool save = false ) : packet_req_t( nullptr, 0U, save ) {}

            packet_req_t( const uint8_t* freqs, size_t count, bool save = false ) :
                packet_t( token_t::emVALUE, ( freqs == nullptr || count == 0 )? 3U : 6U + count )
            {
                uint8_t* p = body;

                if( freqs == nullptr || count == 0 )
                {
                    *(p++) = 1;
                } else {
                    *(p++) = 0;

                    *(p++) = 0x01;
                    _value_t<uint16_t>::set( p, count );
                    p += 2;
                    memcpy( p, freqs, count );
                    p += count;
                }

                *(p++) = 0x02;
                *(p++) = save? 1U : 0U;

                set_crc( p - body );
            }

            uint8_t body[emMAX_BODY + emSIZ_CRC];
        };

        /*********************************************************************
         * @brief 读头rf-freq频点查询回应封包
         */
        template<> struct packet_res_t< _token_t< 0x00, 0x02, mid_t::emGET_RF_FREQ > > : public packet_t
        {
            using token_t = _token_t< 0x00, 0x02, mid_t::emGET_RF_FREQ >;

            enum : uint_t { emFRQ_COUNT = 255U, emBODY = 2 + emFRQ_COUNT, emSIZE = 0U };

            uint8_t body[emBODY + emSIZ_CRC];

            packet_res_t() : packet_t( token_t::emVALUE, 0U ) {}

            void mode( uint8_t v ) { body[0] = v; }
            uint8_t mode() const { return body[0]; }

            void count( uint8_t v ) { body[1] = v; }
            uint8_t count() const { return body[1]; }

            void freq( uint8_t i, uint8_t v ) { body[2 + v] = v; }
            uint8_t  freq( uint8_t i ) const { return body[2 + i]; }

            uint8_t* freqs() { return body + 2; }
            const uint8_t* freqs() const { return body + 2; }
        };

        /*********************************************************************
         * @brief 读头标签上报设置请求封包
         */
        template<> struct packet_req_t< _token_t< 0x00, 0x02, mid_t::emSET_TAG > > : public packet_t
        {
            using token_t = _token_t< 0x00, 0x02, mid_t::emSET_TAG >;

            enum : size_t { emBODY = 3U };

            packet_req_t( uint16_t timeout = 0U, uint8_t rssi = 0U ) :
                packet_t( token_t::emVALUE, emBODY )
            {
                body[0] = 1U;
                _value_t< uint16_t >::set( body + 1, timeout );

                body[3] = 2U;
                body[4] = rssi;

                set_crc( emBODY );
            }

            uint8_t body[emBODY + emSIZ_CRC];
        };

        /*********************************************************************
         * @brief 读头标签上报查询回应封包
         */
        template<> struct packet_res_t< _token_t< 0x00, 0x02, mid_t::emGET_TAG > > : public packet_t
        {
            using token_t = _token_t< 0x00, 0x02, mid_t::emGET_TAG >;

            enum : uint_t { emBODY = 3U, emSIZE = emBODY + emMIN_PKG };

            uint8_t body[emBODY + emSIZ_CRC];

            packet_res_t() : packet_t( token_t::emVALUE, emBODY ) {}

            void time( uint16_t v ) { _value_t< uint16_t >::set( body, v ); }
            uint16_t time() const { return _value_t< uint16_t >::get( body ); }

            void rssi( uint8_t v ) { body[2] = v; }
            uint8_t rssi() const { return body[2]; }
        };

        /*********************************************************************
         * @brief 读头EPC参数设置请求封包
         */
        template<> struct packet_req_t< _token_t< 0x00, 0x02, mid_t::emSET_EPC > > : public packet_t
        {
            using token_t = _token_t< 0x00, 0x02, mid_t::emSET_EPC >;

            enum : size_t { emBODY = 8U };

            packet_req_t( uint8_t speed = 0xff, uint8_t qv = 7U, uint8_t session = 2U , uint8_t target = 0U ) :
                packet_t( token_t::emVALUE, emBODY )
            {
                uint8_t* p = body;

                *(p++) = 0x01;    *(p++) = speed;
                *(p++) = 0x02;    *(p++) = qv;
                *(p++) = 0x03;    *(p++) = session;
                *(p++) = 0x04;    *(p++) = target;

                set_crc( emBODY );
            }

            uint8_t body[emBODY + emSIZ_CRC];
        };

        /*********************************************************************
         * @brief 读头EPC参数查询回应封包
         */
        template<> struct packet_res_t< _token_t< 0x00, 0x02, mid_t::emGET_EPC > > : public packet_t
        {
            using token_t = _token_t< 0x00, 0x02, mid_t::emGET_EPC >;

            enum : uint_t { emBODY = 4U, emSIZE = emBODY + emMIN_PKG };

            uint8_t body[emBODY + emSIZ_CRC];

            packet_res_t() : packet_t( token_t::emVALUE, emBODY ) {}

            void speed( uint8_t v ) { body[0] = v; }
            uint8_t speed() const { return body[0]; }

            void qv( uint8_t v ) { body[1] = v; }
            uint8_t qv() const { return body[1]; }

            void session( uint8_t v ) { body[2] = v; }
            uint8_t session() const { return body[2]; }

            void target( uint8_t v ) { body[3] = v; }
            uint8_t target() const { return body[3]; }
        };

        /*********************************************************************
         * @brief 读头hold参数设置请求封包
         */
        template<> struct packet_req_t< _token_t< 0x00, 0x02, mid_t::emSET_HOLD > > : public packet_t
        {
            using token_t = _token_t< 0x00, 0x02, mid_t::emSET_HOLD >;

            enum : uint_t { emBODY = 6U, emSIZE = emBODY + packet_t::emMIN_PKG };

            packet_req_t( uint16_t ant = 1U, uint16_t freq = 1U ) :
                packet_t( token_t::emVALUE, emBODY )
            {
                body[0] = 0x01;
                _value_t< uint16_t >::set( body + 1, ant );

                body[3] = 0x02;
                _value_t< uint16_t >::set( body + 4, freq );

                set_crc( emBODY );
            }

            uint8_t body[emBODY + emSIZ_CRC];
        };

        /*********************************************************************
         * @brief 读头hold参数查询回应封包
         */
        template<> struct packet_res_t< _token_t< 0x00, 0x02, mid_t::emGET_HOLD > > : public packet_t
        {
            using token_t = _token_t< 0x00, 0x02, mid_t::emGET_HOLD >;

            enum : uint_t { emBODY = 6U, emSIZE = emBODY + emMIN_PKG };

            uint8_t body[emBODY + emSIZ_CRC];

            packet_res_t() : packet_t( token_t::emVALUE, emBODY ) {}

            void ant( uint16_t v ) { _value_t< uint16_t >::set( body + 1, v ); }
            uint8_t ant() const { return _value_t< uint16_t >::get( body + 1 ); }

            void freq( uint16_t v ) { _value_t< uint16_t >::set( body + 4, v ); }
            uint8_t freq() const { return _value_t< uint16_t >::get( body + 4 ); }
        };

        /*********************************************************************
         * @brief 读头停止请求封包
         */
        template<> struct packet_req_t< _token_t< 0x00, 0x02, mid_t::emSTOP > > : public packet_t
        {
            using token_t = _token_t< 0x00, 0x02, mid_t::emSTOP >;

            packet_req_t() : packet_t( token_t::emVALUE, 0 )
            {
                set_crc( 0 );
            }

            uint16_t crc16;
        };

        /*********************************************************************
         * @brief 读头写请求封包
         */
        template<> struct packet_req_t< _token_t< 0x00, 0x02, mid_t::emWRITE > > : public packet_t
        {
            using token_t = _token_t< 0x00, 0x02, mid_t::emWRITE >;

            enum : size_t { emBODY = emMAX_BODY + emSIZ_CRC, emANTS = 0U, emPOS = 4U, emADDR = 5U, emDATA = 7U };

            packet_req_t( uint32_t ants, const hude::buffer_t& dat ) :
                packet_req_t( ants, dat, 1U, 0U, {}, 0U, 0U, {} ) {}

            packet_req_t( uint32_t ants, const hude::buffer_t& dat, uint8_t pos, uint16_t addr ) :
                packet_req_t( ants, dat, pos, addr, {}, 0U, 0U, {} ) {}

            packet_req_t( uint32_t ants, const hude::buffer_t& dat, uint8_t pos, uint16_t addr, const hude::buffer_t& pwd ) :
                packet_req_t( ants, dat, pos, addr, {}, 0U, 0U, pwd ) {}

            packet_req_t( uint32_t ants, const hude::buffer_t& dat, uint8_t pos, uint16_t addr,
                const hude::buffer_t& mdat, uint8_t mpos, uint16_t maddr,
                const hude::buffer_t& pwd = {} ) : packet_t( token_t::emVALUE, 0 )
            {
                _value_t< uint32_t >::set( body + emANTS, ants );

                uint8_t* p = body + emDATA;

                body[emPOS]  = pos & 0x03;
                _value_t< uint16_t >::set( body + emADDR, addr );
                _value_t< uint16_t >::set( p, dat.size() );  p += 2U;
                memcpy( p, &(dat[0]), dat.size() ); p += dat.size();

                *(p++) = 0x01; //pid

                *(p++) = mpos;
                _value_t< uint16_t >::set( p, maddr );  p += 2U;
                *(p++) = mdat.size();
                memcpy( p, &(mdat[0]), mdat.size() ); p += mdat.size();

                if( ! pwd.empty() )
                {
                    *(p++) = 0x02; //pid
                    memcpy( p, &(pwd[0]), pwd.size() ); p += pwd.size();
                }

                set_crc( p - body );
            }

            uint8_t body[emBODY];
        };

        /*********************************************************************
         * @brief 读头写请求回应封包
         */
        template<> struct packet_res_t< _token_t< 0x00, 0x02, mid_t::emWRITE > > : public packet_t
        {
            using token_t = _token_t< 0x00, 0x02, mid_t::emWRITE >;

            enum : uint_t { emBODY = 3, emSIZE = 0U };

            packet_res_t() : packet_res_t( 0U, 0U ) {}

            packet_res_t( uint8_t e, uint16_t a ) : packet_t( token_t::emVALUE, emBODY )
            {
                error( e );
                addr( a );
                set_crc( emBODY );
            }

            uint8_t error() const { return body[0]; }
            void error( uint8_t v ) { body[0] = v; }

            uint16_t addr() const { return _value_t< uint16_t >::get( body + 1 ); }
            void addr( uint16_t v ) { _value_t< uint16_t >::set( body + 1, v ); }

            uint8_t body[emBODY + emSIZ_CRC];
        };

        /*********************************************************************
         * @brief 读头盘存请求封包
         */
        template<> struct packet_req_t< _token_t< 0x00, 0x02, mid_t::emREAD > > : public packet_t
        {
            using token_t = _token_t< 0x00, 0x02, mid_t::emREAD >;

            enum : size_t { emBODY = 8U, emANTS = 0U, emKEEP = 4U, emMONZA = 5U };

            packet_req_t( uint32_t ants, bool keep = false, bool fast = true, bool foucs = false ) : packet_t( token_t::emVALUE, emBODY )
            {
                _value_t< uint32_t >::set( body + emANTS, ants );

                body[emKEEP]  = keep? 1U : 0U;

                body[emMONZA + 0] = 0x0a;
                body[emMONZA + 1] = fast? 1U : 0U;
                body[emMONZA + 2] = foucs? 1U : 0U;

                set_crc( emBODY );
            }

            uint8_t body[emBODY];

            uint16_t crc16;
        };

        /*********************************************************************
         * @brief 读头盘存结束事件封包
         */
        template<> struct packet_evt_t< _token_t< 0x01, 0x02, mid_t::emREAD_END > > : public packet_t
        {
            using token_t = _token_t< 0x01, 0x02, mid_t::emREAD_END >;

            enum : size_t { emBODY = 1U };

            uint8_t body;

            packet_evt_t( uint8_t ret ) : packet_t( token_t::emVALUE, emBODY ), body( ret )
            {
                set_crc( emBODY );
            }

            uint8_t result() const { return body; }
        };

        /*********************************************************************
         * @brief 读头盘存切换天线事件封包
         */
        template<> struct packet_evt_t< _token_t< 0x01, 0x02, mid_t::emREAD_ANT > > : public packet_t
        {
            using token_t = _token_t< 0x01, 0x02, mid_t::emREAD_ANT >;

            enum : size_t { emBODY = 1U };

            uint8_t body;

            packet_evt_t( uint8_t ant ) : packet_t( token_t::emVALUE, emBODY ), body( ant )
            {
                set_crc( emBODY );
            }

            uint8_t result() const { return body; }
        };

        /*********************************************************************
         * @brief 读头盘存标签事件封包
         */
        template<> struct packet_evt_t< _token_t< 0x01, 0x02, mid_t::emREAD_TAG > > : public packet_t
        {
            using token_t = _token_t< 0x01, 0x02, mid_t::emREAD_TAG >;

            enum : size_t { emBODY = emMAX_BODY + emSIZ_CRC, emFIXLE = 3U };

            struct item_t
            {
                uint8_t s;
                void*   p;
            };

            uint8_t body[emBODY];

            packet_evt_t() : packet_t( token_t::emVALUE, 0U ) {}

            packet_evt_t( const void* e, size_t n, uint8_t ant = 1U, uint8_t rssi = 0x39U, uint32_t freq = 915000U, uint16_t pc = 0x0004U ) :
                packet_t( token_t::emVALUE, emMAX_BODY )
            {
                uint8_t* p = body;

                // data
                {
                    _value_t< uint16_t >::set( p, n );
                    p += 2;

                    memcpy( p, e, n );
                    p += n;
                }

                // PC value
                {
                    _value_t< uint16_t >::set( p, pc );
                    p += 2;
                }

                // antenna
                {
                    *(p++) = ant;
                }

                // rssi
                {
                    *(p++) = 0x01;
                    *(p++) = rssi;
                }

                // freq
                {
                    *(p++) = 0x08;
                    *(p++) = freq;
                }

                // 相位
                {
                    *(p++) = 0x09;
                    *(p++) = 0x39;
                }

                n = p - body;

                this->lenght( n );
                set_crc( n );
            }

            uint16_t siz_epc() const { return _value_t< uint16_t >::get( body ); }

            const uint8_t* _value( void* d, const uint8_t* p, uint8_t s ) const
            {
                switch ( s )
                {
                case 1U:  if( d ) (*((uint8_t* )d)) = _value_t< uint8_t  >::get( p );   break;
                case 2U:  if( d ) (*((uint16_t*)d)) = _value_t< uint16_t >::get( p );   break;
                case 4U:  if( d ) (*((uint32_t*)d)) = _value_t< uint32_t >::get( p );   break;
                case 0U:  s = _value_t< uint16_t >::get( p ) + 2U; break;
                default: break;
                }

                return p + s;
            }

            bool tag( tag_t& v ) const
            {
                const item_t items[] =
                {
                    { 0, nullptr }, { 2, &v.pc   }, { 1, &v.ant  },
                    { 1, &v.rssi }, { 1, nullptr }, { 0, nullptr },
                    { 0, nullptr }, { 0, nullptr }, { 1, nullptr },
                    { 8, nullptr }, { 4, &v.freq }, { 1, nullptr }
                };

                const uint8_t* p = body;
                const uint8_t* e = body + lenght();

                // id
                uint8_t len = _value_t< uint16_t >::get( p );
                p += sizeof( uint16_t );
                v.epc.assign( p, p + len );
                p += len;

                // pc
                p = this->_value( items[1].p, p, items[1].s );

                // ant
                p = this->_value( items[2].p, p, items[2].s );

                const item_t* item;
                uint8_t idx;

                while( p < e )
                {
                    idx = *p;

                    // 超过0x09的数据不需要了
                    if( idx > 0x09 ) break;

                    if( idx == 0x03 )
                    {
                        len = _value_t<uint16_t>::get( ++p );
                        p += 2;

                        v.tid.assign( p, p + len );
                        p += len;
                    } else {
                        item = ( items + 2U) + idx;

                        p = this->_value( item->p, p + 1, item->s );
                    }
                }

                v.utc = (uint64_t)now();

                return true;
            }
        };

    } // namespace x2000
} // namespace pgl

#endif // __packet_x2000_ieu89e8u89u8__
